package com.echat.serviceapigateway.security.interceptor;

import com.echat.commonlib.constant.ErrorCode;
import com.echat.commonlib.constant.ErrorCodeMsg;
import com.echat.commonlib.exception.exc.EchatSecurityException;
import com.echat.serviceapigateway.security.cache.AccessCacher;
import com.echat.serviceapigateway.security.cache.RedisTokenCacher;
import com.echat.serviceapigateway.security.service.AuthorizationService;
import com.echat.serviceapigateway.security.service.IpWhiteListService;
import com.echat.serviceapigateway.security.service.UserService;
import com.echat.serviceapigateway.security.tool.IPUtils;
import com.echat.serviceapigateway.security.tool.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
 * Created by chenmohan on 2018/08/31
 *
 * @description 拦截请求并检查请求中的access_token是否合法
 */
@Component
@Log4j2
public class AuthorizedInterceptor {

    @Autowired
    RedisTokenCacher redisTokenCacher;

    @Autowired
    AccessCacher accessCacher;

    @Autowired
    AuthorizationService authorizationService;

    @Autowired
    IpWhiteListService ipWhiteListService;

    @Autowired
    UserService userService;

    public boolean preHandle(HttpServletRequest request, String userIdString, String uri) {
        //用户调用接口时的ip
        String ip = IPUtils.getRequestIP(request);
        //检查是否缓存过认证鉴权结果
        Boolean access = accessCacher.isAccess(userIdString, uri, ip);
        if (access != null) {
            return access;
        }
        //非空检查
        String accessToken = request.getParameter("accessToken");
        if (StringUtils.isEmpty(accessToken)) {
            throw new EchatSecurityException(ErrorCode.IDENTITY_CHECK_FAILED, "accessToken is null");
        }
        String accessKey = request.getParameter("accessKey");
        if (StringUtils.isEmpty(accessKey)) {
            throw new EchatSecurityException(ErrorCode.IDENTITY_CHECK_FAILED, "accessKey is null");
        }
        //判断accessKey是否相同
        String validateAccessKey = redisTokenCacher.getAccessKey(accessToken);
        if (!accessKey.equals(validateAccessKey)) {
            throw new EchatSecurityException(ErrorCode.INVAILD_ACCESS_TOKEN, ErrorCodeMsg.INVAILD_ACCESS_TOKEN);
        }
        //检查accessKey是否真的存在
        Long userId = Long.valueOf(userService.getUserIdByAccessKey(accessKey));
        if (userId == null) {
            throw new EchatSecurityException(ErrorCode.INVAILD_ACCESS_TOKEN, ErrorCodeMsg.INVAILD_ACCESS_TOKEN);
        }

        //检查用户ip是否在白名单内
        if (userIdString != null && !ipWhiteListService.isExistIpWhiteList(Long.valueOf(userIdString), ip)) {
            throw new EchatSecurityException(ErrorCode.IP_LIMIT, ErrorCodeMsg.IP_LIMIT);
        }

        //检查用户是否具有访问该uri的权限
        log.info("[" + LocalDateTime.now() + "]AuthorizedInterceptor -- access uri:" + uri + " ,userId: " + userId);
        boolean res = authorizationService.isAuthorized(userId, uri);
            //将结果缓存起来
        accessCacher.cacheAccess(userIdString, uri, ip, res);
        return res;

    }


}
